package agents;

import model.Artifact;
import jade.content.lang.sl.SLCodec;
import jade.core.Agent;
import jade.core.behaviours.Behaviour;
import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.OneShotBehaviour;
import jade.domain.FIPANames;
import jade.domain.mobility.MobilityOntology;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.UnreadableException;

@SuppressWarnings("serial")
public class ParticipantAgent extends Agent {

	protected void beforeClone() {
		// -------------------------------

		System.out.println(this.getLocalName() + ": beforeClone()");
		postCloning();
	}

	protected void afterClone() {
		System.out.println(this.getLocalName() + ": afterClone()");
		init();
		postCloning();
	}

	private void postCloning() {
		// Listen for auction messages
		addBehaviour(new ListenToAuctionBehaviour());
		addBehaviour(new ListenToAuctionStartBehaviour());
	}

	void init() {
		// Register language and ontology
		getContentManager().registerLanguage(new SLCodec());
		getContentManager().registerOntology(MobilityOntology.getInstance());
	}
/*
	void registerAtDF() {
		// Register as an auction participant at the DF
		ServiceDescription sd = new ServiceDescription();
		sd.setType("auction-participant");
		sd.setName(getLocalName() + Math.round(Math.random() * 1000));
		// System.out.println("Registering " + sd.getName()
		// + " as a new auction-participant");
		ServiceDescription[] sds = new ServiceDescription[1];
		sds[0] = sd;
		addBehaviour(new RegisterServiceBehaviour(getAID(), sds));
	}
*/
	@Override
	protected void setup() {

		System.out.println(this.getLocalName() + ": Running setup()");

		addBehaviour(new CloneMyselfBehaviour());
	}

	private class CloneMyselfBehaviour extends OneShotBehaviour {

		@Override
		public void action() {
			doClone(myAgent.here(), myAgent.getLocalName() + "_c");
		}

	}

	private class ListenToAuctionStartBehaviour extends Behaviour {

		private boolean msgReceived;
		
		@Override
		public void action() {
			ACLMessage msg = myAgent.receive(MessageTemplate
					.MatchPerformative(ACLMessage.REQUEST));
			if (msg != null) {
				if(msg.getContent().equals("Auction?")) {
					ACLMessage reply = msg.createReply();
					reply.setPerformative(ACLMessage.CONFIRM);
					myAgent.send(reply);
					msgReceived = true;
				}
			}
			else { block(); }
		}

		@Override
		public boolean done() {
			return msgReceived;
		}
	}

	private class ListenToAuctionBehaviour extends CyclicBehaviour {
		private int estimatedObjectValue = 0;

		@Override
		public void action() {
			ACLMessage msg = myAgent
					.receive(MessageTemplate
							.MatchProtocol(FIPANames.InteractionProtocol.FIPA_DUTCH_AUCTION));
			if (msg != null) {
				Object content = null;
				if (msg.hasByteSequenceContent())
					try {
						content = msg.getContentObject();
					} catch (UnreadableException e1) {
						e1.printStackTrace();
					}
				else
					content = msg.getContent();

				switch (msg.getPerformative()) {

				case ACLMessage.INFORM: {
					// Check the content
					if (content instanceof Artifact) {
						// Do an estimation of the artifacts value
						estimatedObjectValue = (int) (13000 + (Math.round(Math
								.random() * 7000)));
						System.out.println(myAgent.getLocalName()
								+ ": Estimated artifact value is: "
								+ estimatedObjectValue);
					}
					// If we got here, the inform is for announcing a closed
					// auction
					else if (content instanceof String) {
						System.out
								.println(myAgent.getLocalName()
										+ ": was notified that an auction was closed: "
										+ (String) content);
					} else {
						System.out
								.println("The received content wasn't what we expected (ProfilerAgent).");
					}

					break;
				}
				case ACLMessage.ACCEPT_PROPOSAL: {
					System.out.println(myAgent.getLocalName()
							+ ": won the auction!");
					break;
				}
				case ACLMessage.REJECT_PROPOSAL: {
					System.out
							.println(myAgent.getLocalName()
									+ ": made a bid but was not the first one to do so :(");
					break;
				}
				case ACLMessage.CFP: {
					if (content instanceof Integer) {
						int offeredPrice = (Integer) content;

						ACLMessage reply = msg.createReply();
						reply.setPerformative(ACLMessage.PROPOSE);

						// If we want to buy it
						if (offeredPrice <= estimatedObjectValue) {
							reply.setContent("ACCEPT");
						}
						// If we don't want to buy it
						else {
							reply.setContent("REFUSE");
						}

						myAgent.send(reply);

					}
					break;
				}

				default:
					break;
				}
			} else {
				block();
			}
		}
	}
}
